﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using Apollo;

namespace AlgoMS
{
    public class AlgoMSOrder : ApolloComplexOrder, IApolloTradingListener
    {
        ApolloOrder entryOrder = null;
        private AlgoMSContract subContract;  //报价合约
        private AlgoMSContract primaryContract;  //基准合约
        private AlgoMSStrategy msStrategy;
        private Dictionary<long, long> sumVolume; //累计成交量

        public AlgoMSOrder(string parentName, string name, long qty, long price, ApolloOrderDirection direct,
            AlgoMSContract contraceInfo, AlgoMSContract primaryContract, AlgoMSStrategy strategy)
            : base(contraceInfo.getTrader(), parentName, name, contraceInfo.getInstrId(), contraceInfo.getProductInfo())
        {
            this.quantity = qty;
            this.price = price;
            this.direction = direct;
            this.subContract = contraceInfo;
            this.primaryContract = primaryContract;
            this.msStrategy = strategy;
            this.sumVolume = new Dictionary<long, long>();
        }

        public override void onApolloRtnOrder(ApolloOrderField order, ApolloExchangeEventContext context)
        {
            ApolloGlobal.getCore().debugPrint("------AlgoMS onApolloRtnOrder orderRef=[{0}] instr=[{1}] status=[{2}] filledAmount=[{3}] qty=[{4}]******", order.orderRef, order.instrumentId, order.status, order.filledAmount, order.quantity);
            /*
            if (order.status == ApolloOrderStatus.AllTraded || order.status == ApolloOrderStatus.PartTradedQueueing)
            {
                
                if (order.instrumentId == subContract.getInstrId())
                {
                    if (order.direction == ApolloOrderDirection.Buy)
                    {
                        // 对冲卖方向
                        long hedgeVol = msStrategy.hedgingOrder(subContract.getInstrId(), subContract.getRatio(), order.quantity, order.filledAmount, order.orderRef, order.direction, order.price);
                        if (hedgeVol == 0)
                        {
                            return;
                        }
                        
                        // 卖的时候,价格按照市场买价-1Tick,确保能被买
                        //long price = msStrategy.getLastBidPrice(primaryContract.getInstrId()) - primaryContract.getProductInfo().TickValue;

                        // 卖的时候,价格按照计算出拟报价时候的买价-1Tick
                        long price = order.price + (primaryContract.getSellThrd() - subContract.getBuyThrd()) - primaryContract.getProductInfo().TickValue;

                        ApolloGlobal.getCore().debugPrint("******在原单买方向有成交，成交量=[{0}] 对冲数量为[{1}] 对冲价格=[{2}]******", order.filledAmount, hedgeVol, price);

                        entryOrder = ApolloOrder.createOrder(primaryContract.getTrader(), parentName, name, primaryContract.getInstrId(), primaryContract.getProductInfo(),
                                hedgeVol, price, ApolloOrderDirection.Sell);
                        entryOrder.addTradingListener(this);
                        trader.getFront().getOrderProcessor().putInsertOrder(entryOrder);
                    }
                    else
                    {
                        long hedgeVol = msStrategy.hedgingOrder(subContract.getInstrId(), subContract.getRatio(), order.quantity, order.filledAmount, order.orderRef, order.direction, order.price);
                        if (hedgeVol == 0)
                        {
                            return;
                        }
                        
                        // 买的时候,价格按照市场卖价+1Tick，确保能有卖
                        //long price = msStrategy.getLastAskPrice(primaryContract.getInstrId()) + primaryContract.getProductInfo().TickValue;

                        // 买的时候,价格按照计算出拟报单时候的卖价+1Tick
                        long price = order.price + (primaryContract.getBuyThrd() - subContract.getSellThrd()) + primaryContract.getProductInfo().TickValue;

                        ApolloGlobal.getCore().debugPrint("******在原单卖方向有成交，成交量=[{0}] 对冲数量为[{1}] 对冲价格=[{2}]******", order.filledAmount, hedgeVol, price);

                        entryOrder = ApolloOrder.createOrder(primaryContract.getTrader(), parentName, name, primaryContract.getInstrId(), primaryContract.getProductInfo(),
                                hedgeVol, price, ApolloOrderDirection.Buy);
                        entryOrder.addTradingListener(this);
                        trader.getFront().getOrderProcessor().putInsertOrder(entryOrder);
                    }
                }
                if (order.status == ApolloOrderStatus.AllTraded)
                {
                    entryOrder = null;
                    reject();
                } 
            }
            */

        }

        public override void onApolloRtnTrade(ApolloTradeField trade, ApolloExchangeEventContext context)
        {
            ApolloGlobal.getCore().debugPrint("------AlgoMS onApolloRtnTrade orderRef=[{0}] instr=[{1}] volume=[{2}]******", trade.orderRef, trade.instrumentId, trade.volume);
 
            if (trade.instrumentId == subContract.getInstrId())
            {
                if (!sumVolume.ContainsKey(trade.orderRef))
                {
                    sumVolume.Add(trade.orderRef, 0);
                }
                sumVolume[trade.orderRef] = sumVolume[trade.orderRef] + trade.volume;

                ApolloGlobal.getCore().debugPrint("------orderRef=[{0}] sumVol=[{1}] ", trade.orderRef, sumVolume[trade.orderRef]);
                if (trade.direction == ApolloOrderDirection.Buy)
                {
                    // 对冲卖方向
                    //long hedgeVol = msStrategy.hedgingOrder(subContract.getInstrId(), subContract.getRatio(), this.quantity, trade.volume, trade.orderRef, trade.direction, trade.price);
                    long qty = this.quantity - sumVolume[trade.orderRef];
                    long fa = sumVolume[trade.orderRef];
                    long hedgeVol = msStrategy.hedgingOrder(subContract.getInstrId(), subContract.getRatio(), qty, fa, trade.orderRef, trade.direction, this.price);
                    if (hedgeVol == 0)
                    {
                        return;
                    }

                    // 卖的时候,价格按照市场买价-1Tick,确保能被买
                    //long price = msStrategy.getLastBidPrice(primaryContract.getInstrId()) - primaryContract.getProductInfo().TickValue;

                    // 卖的时候,价格按照计算出拟报价时候的买价-1Tick
                    long price = trade.price + (primaryContract.getSellThrd() - subContract.getBuyThrd()) - primaryContract.getProductInfo().TickValue;

                    ApolloGlobal.getCore().debugPrint("******在原单买方向有成交，累计成交量=[{0}] 本次对冲数量为[{1}] 对冲价格=[{2}]******", sumVolume[trade.orderRef], hedgeVol, price);

                    entryOrder = ApolloOrder.createOrder(primaryContract.getTrader(), parentName, name, primaryContract.getInstrId(), primaryContract.getProductInfo(),
                            hedgeVol, price, ApolloOrderDirection.Sell);
                    entryOrder.addTradingListener(this);
                    trader.getFront().getOrderProcessor().putInsertOrder(entryOrder);
                }
                else
                {
                    //long hedgeVol = msStrategy.hedgingOrder(subContract.getInstrId(), subContract.getRatio(), this.quantity, trade.volume, trade.orderRef, trade.direction, trade.price);
                    long qty = this.quantity - sumVolume[trade.orderRef];
                    long hedgeVol = msStrategy.hedgingOrder(subContract.getInstrId(), subContract.getRatio(), qty, sumVolume[trade.orderRef], trade.orderRef, trade.direction, this.price);
                    if (hedgeVol == 0)
                    {
                        return;
                    }

                    // 买的时候,价格按照市场卖价+1Tick，确保能有卖
                    //long price = msStrategy.getLastAskPrice(primaryContract.getInstrId()) + primaryContract.getProductInfo().TickValue;

                    // 买的时候,价格按照计算出拟报单时候的卖价+1Tick
                    long price = trade.price + (primaryContract.getBuyThrd() - subContract.getSellThrd()) + primaryContract.getProductInfo().TickValue;

                    ApolloGlobal.getCore().debugPrint("******在原单卖方向有成交，累计成交量=[{0}] 本次对冲数量为[{1}] 对冲价格=[{2}]******", sumVolume[trade.orderRef], hedgeVol, price);

                    entryOrder = ApolloOrder.createOrder(primaryContract.getTrader(), parentName, name, primaryContract.getInstrId(), primaryContract.getProductInfo(),
                            hedgeVol, price, ApolloOrderDirection.Buy);
                    entryOrder.addTradingListener(this);
                    trader.getFront().getOrderProcessor().putInsertOrder(entryOrder);
                }
            }

        }

        public override bool isRegularOrder()
        {
            return false;
        }

        public override bool isSupportedFront(ApolloFront front)
        {
            return true;
        }

        protected override bool rejectHandler()
        {
            if (entryOrder != null)
            {
                entryOrder.removeTradingListener(this);
                trader.getFront().getOrderProcessor().putCancelOrder(entryOrder);
            }
            return true;
        }

        protected override bool submitHandler()
        {
            entryOrder = ApolloOrder.createOrder(trader, parentName, name, instrumentId, productInfo, quantity, price, direction);
            entryOrder.addTradingListener(this);
            trader.getFront().getOrderProcessor().putInsertOrder(entryOrder);
            return true;
        }
    }
}
